package org.gd.science.qr.qrgen;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * Tutorial: http://zxing.org/w/docs/javadoc/index.html
 */
public class QRCodeGenerator {

    private String text = QRCodeGenerator.class.getName();
    private String path;
    private String encoding = "UTF-8";
    private Color fgColor = Color.BLACK;
    private Color bgColor = Color.WHITE;

    public String getText() {
        return text;
    }

    public QRCodeGenerator setText(String text) {
        this.text = text;
        return this;
    }

    public String getPath() {
        return path;
    }

    public QRCodeGenerator setPath(String path) {
        this.path = path;
        return this;
    }

    public String getEncoding() {
        return encoding;
    }

    public QRCodeGenerator setEncoding(String encoding) {
        this.encoding = encoding;
        return this;
    }

    public Color getFgColor() {
        return fgColor;
    }

    public QRCodeGenerator setFgColor(Color fgColor) {
        this.fgColor = fgColor;
        return this;
    }

    public Color getBgColor() {
        return bgColor;
    }

    public QRCodeGenerator setBgColor(Color bgColor) {
        this.bgColor = bgColor;
        return this;
    }

    private Map<EncodeHintType, Object> getProperties() {
        Map<EncodeHintType, Object> hintMap = new HashMap<EncodeHintType, Object>();
        hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
        hintMap.put(EncodeHintType.CHARACTER_SET, getEncoding());
        return hintMap;
    }

    @Deprecated
    public Graphics2D create() {
        try {
            int size = 125;
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            BitMatrix byteMatrix = qrCodeWriter
                    .encode(getText(), BarcodeFormat.QR_CODE, size, size, getProperties());

            int CrunchifyWidth = byteMatrix.getWidth();
            BufferedImage image = new BufferedImage(CrunchifyWidth, CrunchifyWidth, BufferedImage.TYPE_INT_RGB);
            image.createGraphics();

            Graphics2D graphics = (Graphics2D) image.getGraphics();
            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, CrunchifyWidth, CrunchifyWidth);
            graphics.setColor(new Color(200, 0, 0));

            for (int i = 0; i < CrunchifyWidth; i++) {
                for (int j = 0; j < CrunchifyWidth; j++) {
                    if (byteMatrix.get(i, j)) {
                        graphics.fillRect(i, j, 1, 1);
                    }
                }
            }
            String fileType = "png";
            File myFile = new File(getPath());
            ImageIO.write(image, fileType, myFile);

            return graphics;
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
        System.out.println("You have successfully created QR Code.");
        return null;
    }

    public Graphics2D writeTo(Graphics graph) {
        try {
            int size = 200;
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            BitMatrix byteMatrix = qrCodeWriter
                    .encode(getText(), BarcodeFormat.QR_CODE, size, size, getProperties());
            int CrunchifyWidth = byteMatrix.getWidth();
            Graphics2D graphics = (Graphics2D) graph;
            graphics.setColor(getBgColor());
            graphics.fillRect(0, 0, CrunchifyWidth, CrunchifyWidth);
            graphics.setColor(getFgColor());
            for (int i = 0; i < CrunchifyWidth; i++) {
                for (int j = 0; j < CrunchifyWidth; j++) {
                    if (byteMatrix.get(i, j)) {
                        graphics.fillRect(i, j, 1, 1);
                    }
                }
            }
            return graphics;
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
        return null;
    }
}
